package com.iwhalecloud.bss.kite.cucc.service.rule.check;

import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneAdditionalOfferInstService;
import com.iwhalecloud.bss.kite.client.dto.rule.common.DataRuleResult;
import com.iwhalecloud.bss.kite.client.dto.rule.common.RuleConsts;
import com.iwhalecloud.bss.kite.client.enums.RuleEventType;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.SwitchConsts;
import com.iwhalecloud.bss.kite.common.constant.SymbolConsts;
import com.iwhalecloud.bss.kite.common.log.KiteLogger;
import com.iwhalecloud.bss.kite.common.util.*;
import com.iwhalecloud.bss.kite.cucc.client.api.pay.IPaymentService;
import com.iwhalecloud.bss.kite.cucc.client.api.reception.ICustReceptionService;
import com.iwhalecloud.bss.kite.cucc.client.api.rule.ICuccRuleTriggerService;
import com.iwhalecloud.bss.kite.cucc.client.api.rule.check.ICuccCheckService;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.service.rule.check.Impl.MenuLoadingRuleCallTask;
import com.iwhalecloud.bss.kite.cucc.service.rule.check.Impl.MenuLoadingRuleCompletionService;
import com.iwhalecloud.bss.kite.cucc.service.rule.check.util.CuccRuleTrigger;
import com.iwhalecloud.bss.kite.cucc.service.rule.check.util.CuccRuleUtil;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ServiceOfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.util.GeneralSwitchUtils;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.inst.*;
import com.iwhalecloud.bss.kite.service.rule.RuleTrigger;
import com.iwhalecloud.bss.kite.service.rule.RuleUtil;
import com.ztesoft.bss.common.bo.LoginInfo;
import com.ztesoft.bss.common.exception.BssException;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.order.base.consts.KeyValues;
import com.ztesoft.bss.rul.core.client.dto.common.RuleCommonParam;
import com.ztesoft.bss.rul.core.client.dto.kite.KiteRuleResponse;
import com.ztesoft.bss.rul.core.engine.bo.ConditionPromptMsgInst;
import com.ztesoft.bss.rul.core.engine.event.RuleResult;
import com.ztesoft.bss.rul.local.util.AttrUtil;
import com.ztesoft.bss.rul.local.util.LocalRuleUtil;
import com.ztesoft.bss.rul.local.util.RuleDateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Future;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @author
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CuccCheckService implements ICuccCheckService {

    @Autowired
    private ICuccRuleTriggerService cuccRuleTriggerService;

    @Autowired
    private IOperateSceneAdditionalOfferInstService operateSceneAdditionalOfferInstService;

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private ICustReceptionService custReceptionService;

    @Autowired
    private IPaymentService paymentService;

    @Override
    public DataRuleResult onDelOfferInstAcctCheck(String scenInstId , RuleCommonParam ruleCommonParam, KiteOfferInstAcct kiteOfferInstAcct) {
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.onDelOfferInstAcctCheck(scenInstId, ruleCommonParam,kiteOfferInstAcct);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }


    @Override
    public DataRuleResult checkPlatformType(String sceneInstId, RuleCommonParam ruleCommonParam) {
        KiteRuleResponse ruleResponse  = cuccRuleTriggerService.checkPlatformType(sceneInstId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }


    @Override
    @KiteLogger(isWrite = true)
    public Map<String,Object> onInitServiceOfferChangeScene(Map<String,Object> requestParam, List<String> serviceOfferIdList){
        if(KiteListUtils.isEmpty(serviceOfferIdList)){
            return Collections.EMPTY_MAP;
        }
        String staffCode = ContextUtil.getSimpleLoginInfo().getStaffCode();
        String postLanId = ContextUtil.getLoginInfo().getUserInfo().getPostLanId();
        String postProvinceNbr = ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr();
        String orgLevel = ContextUtil.getLoginInfo().getOrgInfo().getOrgLevel() + "";
        Map<String,String> staffInfo = new HashMap<String,String>();
        Map<String,String> userInfo = (Map)requestParam.get("userInfo");
        staffInfo.put("staffCode", staffCode);
        staffInfo.put("postLanId", postLanId);
        staffInfo.put("postProvinceNbr", postProvinceNbr);
        staffInfo.put("orgLevel", orgLevel);
        String custId = userInfo.get("custId");
        Map<String,Object> resultMap = new HashMap<String,Object>();
        CompletionService<Map<String,Object>> service = MenuLoadingRuleCompletionService.INSTANCE.getExecutorCompletionService();
        List<Future<Map<String,Object>>> futureList = new ArrayList<>();
        try{
            for(String serviceOfferId: serviceOfferIdList){
                String serviceOfferName = ServiceOfferCache.get(serviceOfferId).getServiceOfferName();
                List paramList = new ArrayList<HashMap<String,String>>();
                RuleCommonParam ruleCommonParam = CuccRuleUtil.getRuleParam(custId);
                RuleTrigger.setRuleOtherInfo(ruleCommonParam);
                Map<String,String> paramMap = new HashMap<String,String>();
                paramMap.putAll(userInfo);
                paramMap.put("serviceOfferId", serviceOfferId);
                paramMap.put("serviceOfferName",serviceOfferName);
                paramList.add(paramMap);
                Map<String,Object> requestMap = new HashMap<String,Object>();
                requestMap.put("prodInstAcctRels", new JSONArray(paramList));
                requestMap.put("staffInfo", staffInfo);
                requestMap.put("userDetailInfo", requestParam.get("userDetailInfo"));
                requestMap.put("oaAccountInfo", requestParam.get("oaAccountInfo"));
                requestMap.put("goodSku", Lists.newArrayList(userInfo.get("goodsId")));
                requestMap.put("serviceOfferId", serviceOfferId);
                requestMap.put("areaLanId", ContextUtil.getLandId());
                ruleCommonParam.setParams(requestMap);
                MenuLoadingRuleCallTask callTask = new MenuLoadingRuleCallTask(ruleCommonParam, RuleEventType.ET_MENU_LOADING_BEFORE);
                Future<Map<String,Object>> future = service.submit(callTask);
                futureList.add(future);
            }

            for(Future<Map<String,Object>> future : futureList){
                Map<String,Object> returnMap = future.get();
                resultMap.putAll(returnMap);
            }
        }catch(Exception e){
            throw new RuntimeException(e.getCause());
        }
        return resultMap;
    }

    /**
     * 资费校验
     * @param sceneInstId
     * @param ruleCommonParam
     * @return
     */
    @Override
    public List<String>  checkOfferInstFeeList(String sceneInstId,RuleCommonParam ruleCommonParam){
        KiteSceneInst sceneInst =  querySceneInstService.getSceneInst(sceneInstId);
        String rootInstId = sceneInst.getRootInstId();
        String mainOfferId = null;
        List<String> checkOfferInstIdList = new ArrayList<>();
        List<KiteOfferInst> mainOfferInstList = querySceneInstService.listMainOfferInsts(sceneInstId);
        for(KiteOfferInst offerInst : mainOfferInstList){
            if(!checkOfferInstIdList.contains(offerInst.getOfferInstId())){
                checkOfferInstIdList.add(offerInst.getOfferInstId());
                mainOfferId = offerInst.getOfferId();
            }
        }
        if(!checkOfferInstIdList.contains(rootInstId)){
            checkOfferInstIdList.add(rootInstId);
        }

        if(KiteListUtils.isNotEmpty(checkOfferInstIdList)){
            String[] diffFeeTypeOfferIds = Optional.ofNullable(DcPublicCache.getCodea("20211111001", "DIFF_FEE_TYPE_CHECK")).orElse("").split(SymbolConsts.COMMA);
            for(String offerInstId : checkOfferInstIdList){
                List<KiteOfferInst> offerInstList = querySceneInstService.listAdditionalOfferInstsFromMainOfferInst(sceneInst.getCustId(), offerInstId);
                if(KiteListUtils.isEmpty(offerInstList)){
                    continue;
                }

                //将作废资费的预警、告警信息去掉
                for(KiteOfferInst kiteOfferInst:offerInstList) {
                    if (KiteStringUtils.equals(kiteOfferInst.getActionType().name(), ActionType.C.name())) {
                        this.removeOfferInstFeeListSplit(sceneInstId, kiteOfferInst);
                    }
                }

                //排除作废资费
                offerInstList.removeIf(offerInst -> KiteStringUtils.equals(offerInst.getActionType().name(), ActionType.C.name()));

                //校验资费生效模式，失效模式
                this.checkOfferInstFeeEffExpMode(sceneInstId, ruleCommonParam, offerInstList);

                //校验资费连续性
                if (Objects.nonNull(mainOfferId) && KiteStringUtils.equalsAny(mainOfferId, diffFeeTypeOfferIds)) {
                    // 不同资费类型连续性校验
                    this.checkOfferInstFeeContinuanceForDiffType(sceneInstId, ruleCommonParam, offerInstList);
                } else {
                    // 相同资费类型连续性校验
                    this.checkOfferInstFeeContinuance(sceneInstId, ruleCommonParam, offerInstList);
                }

                // 趸交到期是否停机，趸交资费相关校验，不和时间接续放一起，单独抽出来，这里只是告警提示
                this.checkOneOffFeeExpireShutdown(sceneInstId, ruleCommonParam, offerInstList);

                // 趸交订单终止校验规则
                this.singlePaymentFeeTerminationCheck(sceneInstId, ruleCommonParam, offerInstList);

                //新增资费是否选择起租时间生效，告警提示“只选择资费变更不能选择起租时间生效”
                this.checkOneOffFeeEffectiveMode(sceneInstId, ruleCommonParam, offerInstList);
            }
        }
        return checkOfferInstIdList;
    }

    /**
     * 新增资费生效模式为起租时间生效校验
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstList
     */
    private void checkOneOffFeeEffectiveMode(String sceneInstId, RuleCommonParam ruleCommonParam, List<KiteOfferInst> offerInstList) {
        // 只需要校验新增的资费
        List<KiteOfferInst> newOfferInstList = offerInstList.stream().filter(offerInst -> KiteStringUtils.equals(offerInst.getActionType().name(), ActionType.A.name())).collect(Collectors.toList());
        if (KiteListUtils.isEmpty(newOfferInstList)) {
            return;
        }
        Map params = ruleCommonParam.getParams();
        if (KiteMapUtils.isEmpty(params)) {
            params = new HashMap<String, Object>();
            ruleCommonParam.setParams(params);
        }
        params.put("feeCheckFlag", "EffectiveModeCheck");
        this.checkOneOffFeeRentType(sceneInstId, ruleCommonParam, newOfferInstList);
    }

    /**
     * 生效模式为以起租方式开始。校验，提示告警信息
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstFeeList
     */
    public void checkOneOffFeeRentType(String sceneInstId,RuleCommonParam ruleCommonParam,List<KiteOfferInst> offerInstFeeList){
        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(sceneInstId);
        String feeCheckFlag = KiteMapUtils.getString(ruleCommonParam.getParams(), "feeCheckFlag");
        //执行规则校验
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.onAddAdditionalOfferInstCheck(sceneInstId, ruleCommonParam,offerInstFeeList);
        //拼装校验结果
        Map<String,String> checkResultMap = this.getOfferInstFeeCheckResult(ruleResponse);
        String msgCode = KiteMapUtils.getString(checkResultMap, "msgCode");
        if(KiteStringUtils.equals(msgCode, "2")){
            String msgDesc = KiteMapUtils.getString(checkResultMap, "msgDesc");
            String msg = "操作类型只选择\"资费变更\",新增资费的生效模式不能选择\"起租时间生效\"";
            List<String> list = transArray2List(msgDesc.split("#",-1));
            String warnofferInstIds = list.get(0);
            String normalfferInstIds = list.get(1);
            List<String> warnOfferInstIdList = transArray2List(KiteStringUtils.split(warnofferInstIds,SymbolConsts.COMMA));
            List<String> normalOfferInstIdList = transArray2List(KiteStringUtils.split(normalfferInstIds,SymbolConsts.COMMA));
            if (KiteListUtils.isNotEmpty(warnOfferInstIdList)){
                for (String warnOfferInstId : warnOfferInstIdList) {
                    KiteOfferInst warnOfferInst = querySceneInstService.getOfferInst(sceneInst.getCustId(), warnOfferInstId);
                    updateAdditionOfferInstRuleResultAttr(sceneInst, warnOfferInst,"2", msg,"F", feeCheckFlag);
                }
            }
            if (KiteListUtils.isNotEmpty(normalOfferInstIdList)){
                for (String normalOfferInstId : normalOfferInstIdList) {
                    KiteOfferInst normalOfferInst = querySceneInstService.getOfferInst(sceneInst.getCustId(), normalOfferInstId);
                    updateAdditionOfferInstRuleResultAttr(sceneInst, normalOfferInst,"2", msg,"T", feeCheckFlag);
                }
            }
        }
    }

    /**
     * 趸交到期是否停机属性相关校验
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstList
     */
    private void checkOneOffFeeExpireShutdown(String sceneInstId, RuleCommonParam ruleCommonParam, List<KiteOfferInst> offerInstList) {
        // 只需要校验新增的资费
        List<KiteOfferInst> newOfferInstList = offerInstList.stream().filter(offerInst -> KiteStringUtils.equals(offerInst.getActionType().name(), ActionType.A.name())).collect(Collectors.toList());
        if (KiteListUtils.isEmpty(newOfferInstList)) {
            return;
        }
        Map params = ruleCommonParam.getParams();
        if(KiteMapUtils.isEmpty(params)){
            params = new HashMap<String,Object>();
            ruleCommonParam.setParams(params);
        }
        params.put("feeCheckFlag", "expireShutdownCheck");
        // 获取趸交资费与月租费对应关系
        Map<String, List> offerInstFeeListMap = this.getOneOffFeeRelation(newOfferInstList);
        List<KiteOfferInst> checkOfferInstList = new ArrayList<>();
        //校验 同一资费类型
        Set<String> offerInstFeeSet =  offerInstFeeListMap.keySet();
        for(String offerInstFeeType : offerInstFeeSet) {
            List<KiteOfferInst> kiteOfferInstList = offerInstFeeListMap.get(offerInstFeeType);
            //按照生效时间排序
            sortByEffTime(kiteOfferInstList);
            int length = kiteOfferInstList.size();
            if(length > 0){
                for(int i = 0; i < length; i++){
                    checkOfferInstList.clear();
                    checkOfferInstList.add(kiteOfferInstList.get(i));
                    // 表明该条数据不是最后一条
                    if (length - i > 1) {
                        // 每次校验都需要把该条数据后面的数据全部送给规则
                        checkOfferInstList.addAll(kiteOfferInstList.subList(i + 1, length));
                    }
                    this.checkOneOffFeeExpireShutdownSplit(sceneInstId, ruleCommonParam, checkOfferInstList);
                }
            }
        }
    }

    /**
     * 趸交到期是否停机 多个分段校验
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstFeeList
     */
    public void checkOneOffFeeExpireShutdownSplit(String sceneInstId,RuleCommonParam ruleCommonParam,List<KiteOfferInst> offerInstFeeList){
        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(sceneInstId);
        String feeCheckFlag = KiteMapUtils.getString(ruleCommonParam.getParams(), "feeCheckFlag");
        //执行规则校验
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.onAddAdditionalOfferInstCheck(sceneInstId, ruleCommonParam,offerInstFeeList);
        //拼装校验结果
        Map<String,String> checkResultMap = this.getOfferInstFeeCheckResult(ruleResponse);
        KiteOfferInst firstOfferInst = offerInstFeeList.get(0);
        String msgCode = KiteMapUtils.getString(checkResultMap, "msgCode");
        String msgDesc = KiteMapUtils.getString(checkResultMap, "msgDesc");
        String errCode = KiteMapUtils.getString(checkResultMap, "errCode");
        if(KiteStringUtils.equals(msgCode, "0")){
            updateAdditionOfferInstRuleResultAttr(sceneInst, firstOfferInst,"1", msgDesc,"T", feeCheckFlag);
        }
        else if(KiteStringUtils.equals(msgCode, "1")){
            updateAdditionOfferInstRuleResultAttr(sceneInst, firstOfferInst,"1", msgDesc,"F", feeCheckFlag);
        }
    }

    @Override
    public DataRuleResult checkUrgentOrDelay(String sceneInstId, RuleCommonParam ruleCommonParam) {
        List<KiteAttr> commonAttrList = querySceneInstService.listCommonAttrs(sceneInstId);
        commonAttrList = commonAttrList.stream().filter(attr -> (KiteStringUtils.equalsAny(attr.getFieldName(), LocalKeyConsts.REPLACE_A, LocalKeyConsts.REPLACE_Z, LocalKeyConsts.WHOLE_PROCESS_TIME))).collect(Collectors.toList());
        String businessType = querySceneInstService.getExtParameterValue(sceneInstId, "businessType");
        Map<String, Object> ruleParam = new HashMap<>();
        ruleParam.put("urgentOrDelayObject", commonAttrList);
        ruleParam.put("businessType", businessType);

        //获取originValue
        KiteAttr wholeProcessTimeAttr = commonAttrList.stream().filter(attr -> attr.getFieldName().equals(LocalKeyConsts.WHOLE_PROCESS_TIME)).findFirst().orElse(null);
        if(Objects.nonNull(wholeProcessTimeAttr) && KiteStringUtils.isEmpty(wholeProcessTimeAttr.getOriginValue())){
            Map<String,Object> orderInfoMap =(Map)querySceneInstService.getExtParameter(sceneInstId).get("orderInfoMap");
            if(KiteMapUtils.isNotEmpty(orderInfoMap)){
                Map<String,Object> orderInfo = (Map)orderInfoMap.get("ORDER");
                if(KiteMapUtils.isNotEmpty(orderInfo)){
                    List<Map> attrMapList = (List)orderInfo.get("ATTRS");
                    if(KiteListUtils.isNotEmpty(attrMapList)){
                        Map wholeProcessTimeAttrMap = attrMapList.stream().filter(attrItemMap -> KiteStringUtils.equals(KiteMapUtils.getString(attrItemMap, "CODE"),
                            LocalKeyConsts.WHOLE_PROCESS_TIME)).findFirst().orElse(Collections.EMPTY_MAP);
                        String value = KiteMapUtils.getStrValue(wholeProcessTimeAttrMap, "VALUE");
                        if(KiteStringUtils.isNotEmpty(value)){
                            wholeProcessTimeAttr.setOriginValue(value);
                        }
                    }
                }
            }
        }


        ruleCommonParam.setParams(ruleParam);
        KiteRuleResponse ruleResponse  = cuccRuleTriggerService.checkUrgentOrDelay(sceneInstId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }


    /**
     * 资费单个分段校验
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstFeeList
     */
    public void checkOfferInstFeeListSplit(String sceneInstId,RuleCommonParam ruleCommonParam,List<KiteOfferInst> offerInstFeeList){

        Map<String,String> errMsgMap = new HashMap();
        errMsgMap.put("20210201", "一次性费用若存分段。会收多次费用,请确保受理时只填入一段资表");
        errMsgMap.put("20210202", "资费时间不连续，请重新选择");
        errMsgMap.put("20210621", "最后资费默认的失效时间必须为2029-12-31 23：59：59");
        // 最后资费校验标志
        String lastFeeCheckFlag = KiteMapUtils.getString(ruleCommonParam.getParams(), "lastFeeCheckFlag");

        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(sceneInstId);
        //执行规则校验
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.onAddAdditionalOfferInstCheck(sceneInstId, ruleCommonParam,offerInstFeeList);

        //拼装校验结果
        Map<String,String> checkResultMap = this.getOfferInstFeeCheckResult(ruleResponse);
        KiteOfferInst lastOfferInst = offerInstFeeList.get(offerInstFeeList.size()-1);
        String msgCode = KiteMapUtils.getString(checkResultMap, "msgCode");
        String errCode = KiteMapUtils.getString(checkResultMap, "errCode");
        if(KiteStringUtils.equals(msgCode, "0")){
            updateAdditionOfferInstRuleResultAttr(sceneInst,lastOfferInst,"1",KiteMapUtils.getString(errMsgMap, "20210201"),"T", lastFeeCheckFlag);
            updateAdditionOfferInstRuleResultAttr(sceneInst,lastOfferInst,"2",KiteMapUtils.getString(errMsgMap, "20210202"),"T", lastFeeCheckFlag);
            updateAdditionOfferInstRuleResultAttr(sceneInst,lastOfferInst,"2",KiteMapUtils.getString(errMsgMap, "20210621"),"T", lastFeeCheckFlag);
        }
        else if(KiteStringUtils.equals(msgCode, "1")){
            updateAdditionOfferInstRuleResultAttr(sceneInst,lastOfferInst,"1",KiteMapUtils.getString(errMsgMap, errCode),"F", lastFeeCheckFlag);
        }
        else if(KiteStringUtils.equals(msgCode, "2")){
            updateAdditionOfferInstRuleResultAttr(sceneInst,lastOfferInst,"2",KiteMapUtils.getString(errMsgMap, errCode),"F", lastFeeCheckFlag);
        }

    }

    /**
     * 去掉作废的资费单个分段校验
     * @param sceneInstId
     * @param offerInstFeeList
     */
    public void removeOfferInstFeeListSplit(String sceneInstId,KiteOfferInst offerInstFeeList){

        Map<String,String> errMsgMap = new HashMap();
        errMsgMap.put("20210201", "一次性费用若存分段。会收多次费用,请确保受理时只填入一段资表");
        errMsgMap.put("20210202", "资费时间不连续，请重新选择");
        errMsgMap.put("20210621", "最后资费默认的失效时间必须为2029-12-31 23：59：59");
        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(sceneInstId);
        updateAdditionOfferInstRuleResultAttr(sceneInst,offerInstFeeList,"1",KiteMapUtils.getString(errMsgMap, "20210201"),"T", null);
        updateAdditionOfferInstRuleResultAttr(sceneInst,offerInstFeeList,"2",KiteMapUtils.getString(errMsgMap, "20210202"),"T", null);
        updateAdditionOfferInstRuleResultAttr(sceneInst,offerInstFeeList,"2",KiteMapUtils.getString(errMsgMap, "20210621"),"T", null);
    }

    /**
     * 处理资费生效模式和失效模式校验结果
     * @param response
     * @param scneInstId
     */
    public void dealOfferInstFeeEffExpModeResult(KiteRuleResponse response,String scneInstId){
        if(Objects.isNull(response)){
            return ;
        }
        if(response != null && !response.isSuccess()){
            String errMsg = "logId: " + response.getTransId() + "<br>" + response.getMessage();
            throw new BssException(KeyConsts.LOG_MODULE, RuleConsts.RULE_RESPONSE_FAILURE, errMsg, response.getErrorStack());
        }

        List<RuleResult> resultList = response.getCheckRuleResults();
        for(RuleResult ruleResult : resultList){
            List<ConditionPromptMsgInst> conditionPromptMsgInstList = ruleResult.getConditionPromptMsgs();
            if (KiteListUtils.isEmpty(conditionPromptMsgInstList)){
                continue;
            }
            for (ConditionPromptMsgInst conditionPromptMsgInst : conditionPromptMsgInstList){
                /**
                 * 0：校验通过；s
                 * 1（预警）：规则提示语）
                 * 2（告警）：规则提示语,拦截
                 */
                //warnofferInstIds#nomalOfferInstIds#提示信息
                //生效模式校验
                if (KiteStringUtils.equalsAny(conditionPromptMsgInst.getErrorCode().toString(), "20210414","20210415")){
                    String returnMsg = conditionPromptMsgInst.getPromptMessage();
                    if(KiteStringUtils.isNotEmpty(returnMsg)){
                        this.dealEffExpModeCheckMessage(returnMsg, scneInstId);
                    }
                }
            }
        }
    }


    public void dealEffExpModeCheckMessage(String checkRuleReulstMsg,String sceneInstId){
        String msgLevel ="2";
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        String[] arrays = checkRuleReulstMsg.split("#", -1);
        List<String> list = transArray2List(checkRuleReulstMsg.split("#", -1));
        String  warnofferInstIds= list.get(0);
        String  nomalOfferInstIds= list.get(1);
        String checkMsg = list.get(2);
        List<String> nomalOfferInstIdList = transArray2List(KiteStringUtils.split(nomalOfferInstIds, SymbolConsts.COMMA));
        List<String> warnOfferInstIdList = transArray2List(KiteStringUtils.split(warnofferInstIds, SymbolConsts.COMMA));
        if(KiteListUtils.isNotEmpty(nomalOfferInstIdList)){
            for(String nomalOfferInstId :nomalOfferInstIdList){
                KiteOfferInst nomalCheckOfferInstFee = querySceneInstService.getOfferInst(sceneInst.getCustId(), nomalOfferInstId);
                this.updateAdditionOfferInstRuleResultAttr(sceneInst, nomalCheckOfferInstFee,msgLevel,checkMsg, "T", null);
            }
        }

        if(KiteListUtils.isNotEmpty(warnOfferInstIdList)){
            for(String warOfferInstId : warnOfferInstIdList){
                KiteOfferInst warnCheckOfferInstFee = querySceneInstService.getOfferInst(sceneInst.getCustId(), warOfferInstId);
                this.updateAdditionOfferInstRuleResultAttr(sceneInst, warnCheckOfferInstFee,msgLevel,checkMsg, "F", null);
            }
        }
    }

    public Map<String,String> getOfferInstFeeCheckResult(KiteRuleResponse response){
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("msgCode", "0");
        resultMap.put("msgDesc", "校验通过");
        if(Objects.isNull(response)){
            return resultMap;
        }

        if(response != null && !response.isSuccess()){
            String errMsg = "logId: " + response.getTransId() + "<br>" + response.getMessage();
            throw new BssException(KeyConsts.LOG_MODULE, RuleConsts.RULE_RESPONSE_FAILURE, errMsg, response.getErrorStack());
        }

        List<RuleResult> resultList = response.getCheckRuleResults();
        for(RuleResult ruleResult : resultList){
            List<ConditionPromptMsgInst> conditionPromptMsgInstList = ruleResult.getConditionPromptMsgs();
            if (KiteListUtils.isEmpty(conditionPromptMsgInstList)){
                continue;
            }
            for (ConditionPromptMsgInst conditionPromptMsgInst : conditionPromptMsgInstList){
                String promptMessage = conditionPromptMsgInst.getPromptMessage();
                String errorCode = conditionPromptMsgInst.getErrorCode().toString();
                /**
                 * 0：校验通过；s
                 * 1（预警）：规则提示语）
                 * 2（告警）：规则提示语
                 */
                //1:同一个一次性费用，订购了多次，预警【一次性费用若存分段。会收多次费用,请确保受理时只填入一段资表】
                if (KiteStringUtils.equals(errorCode, "20210201")){
                    resultMap.put("msgCode", "1");
                    resultMap.put("msgDesc", promptMessage);
                    resultMap.put("errMsg", promptMessage);
                    resultMap.put("errCode", errorCode);
                    return resultMap;
                }

                //2:非一次性费用，同一个规则订购了多次，需要校验连续性，不连续的话告警就是【资费时间不连续，请重新选择】
                if (KiteStringUtils.equalsAny(errorCode, "20210202", "20210621")){
                    resultMap.put("msgCode", "2");
                    resultMap.put("msgDesc", promptMessage);
                    resultMap.put("errMsg", promptMessage);
                    resultMap.put("errCode", errorCode);
                    return resultMap;
                }

                //21112601:您已选择”趸交到期是否停机”为“否”，趸交资费到期不会自动停机。如需自动停机，请在前面业务属性中调整“趸交到期是否停机”为“是”
                //21112602:趸交到期后将自动停机，如不需要停机，可修改前面业务属性中的“趸交到期是否停机”为“否”
                if (KiteStringUtils.equalsAny(errorCode, "21112601", "21112602")){
                    resultMap.put("msgCode", "1");
                    resultMap.put("msgDesc", promptMessage);
                    resultMap.put("errMsg", promptMessage);
                    resultMap.put("errCode", errorCode);
                    return resultMap;
                }

                //操作类型只选择“资费变更”时，如新增资费选择了“起租时间生效”，则告警
                //20210422:操作类型只选择“资费变更”，新增资费的生效模式不能选择“起租时间生效”
                if (KiteStringUtils.equalsAny(errorCode, "20220216")){
                    resultMap.put("msgCode", "2");
                    resultMap.put("msgDesc", promptMessage);
                    resultMap.put("errMsg", promptMessage);
                    resultMap.put("errCode", errorCode);
                    return resultMap;
                }
            }
        }
        return resultMap;
    }

    /**
     *
     * @param kiteSceneInst 场景实例信息
     * @param offerInst  销售品实例信息
     * @param errorMsg  告警提示信息
     * @param checkFlag  操作表示 T:删除告警信息 F:增加告警信息
     *
     */
    /**
     * 0：校验通过；s
     * 1（预警）：规则提示语）
     * 2（告警）：规则提示语
     */
    public void updateAdditionOfferInstRuleResultAttr(KiteSceneInst kiteSceneInst, KiteOfferInst offerInst, String errorMsgLevel,
                                                      String errorMsg, String checkFlag, String lastFeeCheckFlag){
        String fieldName ="rule_result";
        String custId = kiteSceneInst.getCustId();
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        String staffId = loginInfo.getUserInfo().getUserId()+"";
        StringBuffer newMsgBuffer = new StringBuffer();

        KiteAttr ruleResultAttr = offerInst.getAttr(fieldName);
        String curValue = "";
        if(Objects.nonNull(ruleResultAttr)){
            curValue = KiteStringUtils.isEmpty(ruleResultAttr.getValue())?ruleResultAttr.getDefaultValue():ruleResultAttr.getValue();
        }
        else {
            curValue = "0:校验通过";
        }
        String[] valueArray = KiteStringUtils.split(curValue,SymbolConsts.COLON);
        String searchStr = KiteStringUtils.substring(errorMsg, 5);
        if(KiteStringUtils.equals(checkFlag, "T")){
            if(KiteStringUtils.equals("0", valueArray[0])){
                return;
            }
            else if(KiteStringUtils.equals(valueArray[0],errorMsgLevel)){
                List<String> msgList =transArray2List(KiteStringUtils.split(valueArray[1],SymbolConsts.SEMICOLON));
                if(KiteListUtils.isNotEmpty(msgList)){
                    for(int i =0;i<msgList.size(); i++){
                        if(KiteStringUtils.contains(msgList.get(i), searchStr)){
                            msgList.remove(i);
                        }
                    }
                }

                if(!KiteListUtils.isEmpty(msgList)){
                    newMsgBuffer.append(errorMsgLevel+SymbolConsts.COLON);
                    newMsgBuffer.append(KiteStringUtils.join(msgList,SymbolConsts.SEMICOLON));
                }
                else {
                    newMsgBuffer.append("0" + SymbolConsts.COLON+"校验通过");
                }

            }
        }
        else if(KiteStringUtils.equals(checkFlag, "F")){
            //如果当前校验结果为校验通过
            if(KiteStringUtils.equals("0", valueArray[0])){
                newMsgBuffer.append(errorMsgLevel+SymbolConsts.COLON + errorMsg);
            }
            //如果当前存在预警信息
            else if(KiteStringUtils.equals("1", valueArray[0])){
                //增加告警信息
                if(KiteStringUtils.equals("2", errorMsgLevel)){
                    newMsgBuffer.append(errorMsgLevel+SymbolConsts.COLON+errorMsg);
                }
                else if(KiteStringUtils.equals("1", errorMsgLevel)){
                    if(!KiteStringUtils.contains(valueArray[1], searchStr)){
                        newMsgBuffer.append(valueArray[0]+SymbolConsts.COLON+valueArray[1]+SymbolConsts.SEMICOLON+errorMsg);
                    }
                }
            }
            //添加告警信息
            else if (KiteStringUtils.equals("2", valueArray[0])){
                //如果此时增加预警信息
                if(KiteStringUtils.equals(valueArray[0],errorMsgLevel)
                    && !KiteStringUtils.contains(valueArray[1], searchStr)){
                    // 如果当前是校验最后一条资费的失效时间，并且异常信息不包含改校验结果，则覆盖全部告警信息
                    if (KiteStringUtils.equals(lastFeeCheckFlag, "lastFeeCheck")) {
                        newMsgBuffer = new StringBuffer();
                        newMsgBuffer.append(errorMsgLevel+SymbolConsts.COLON+errorMsg);
                    } else {
                        newMsgBuffer.append(errorMsgLevel+SymbolConsts.COLON+valueArray[1]);
                        newMsgBuffer.append(SymbolConsts.SEMICOLON+errorMsg);
                    }
                }
            }
        }
        if(KiteStringUtils.isNotEmpty(newMsgBuffer.toString())){
            operateSceneAdditionalOfferInstService.updateAdditionalOfferAttr(kiteSceneInst.getSceneInstId(), offerInst.getOfferInstId(),
                fieldName, newMsgBuffer.toString(), newMsgBuffer.toString(), custId, staffId);
        }
    }


    /***
     * 资费连续性校验 同一资费类型
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstList
     */
    public void checkOfferInstFeeContinuance(String sceneInstId,RuleCommonParam ruleCommonParam,List<KiteOfferInst> offerInstList){
        Map params = ruleCommonParam.getParams();
        if(KiteMapUtils.isEmpty(params)){
            params = new HashMap<String,Object>();
            ruleCommonParam.setParams(params);
        }
        params.put("feeCheckFlag", "continuance");


        //资费连续性校验-start
        //获取趸交资费与月租费对应关系
        Map<String, List> offerInstFeeListMap = this.getOneOffFeeRelation(offerInstList);

        List<KiteOfferInst> checkOfferInstList = new ArrayList<>();
        //校验 同一资费类型
        Set<String> offerInstFeeSet =  offerInstFeeListMap.keySet();
        for(String offerInstFeeType : offerInstFeeSet) {
            List<KiteOfferInst> kiteOfferInstList = offerInstFeeListMap.get(offerInstFeeType);
            //按照生效时间排序
            sortByEffTime(kiteOfferInstList);

            checkOfferInstList.clear();
            checkOfferInstList.add(kiteOfferInstList.get(0));
            this.checkOfferInstFeeListSplit(sceneInstId, ruleCommonParam, checkOfferInstList);
            if(kiteOfferInstList.size() >1){
                for(int i = 0;i<kiteOfferInstList.size()-1; i++){
                    checkOfferInstList.clear();
                    checkOfferInstList.add(kiteOfferInstList.get(i));
                    checkOfferInstList.add(kiteOfferInstList.get(i+1));
                    this.checkOfferInstFeeListSplit(sceneInstId,ruleCommonParam,checkOfferInstList);
                }
            }
        }
    }

    /***
     * 资费连续性校验 不同资费类型
     * @param sceneInstId
     * @param ruleCommonParam
     * @param offerInstList
     */
    public void checkOfferInstFeeContinuanceForDiffType(String sceneInstId, RuleCommonParam ruleCommonParam, List<KiteOfferInst> offerInstList) {
        Map params = ruleCommonParam.getParams();
        if (KiteMapUtils.isEmpty(params)) {
            params = new HashMap<String, Object>();
            ruleCommonParam.setParams(params);
        }
        params.put("feeCheckFlag", "continuance");

        //资费连续性校验-start
        List<KiteOfferInst> checkOfferInstList = new ArrayList<>();
        //校验 不同资费类型
        //按照生效时间排序
        sortByEffTime(offerInstList);

        checkOfferInstList.clear();
        checkOfferInstList.add(offerInstList.get(0));
        // 单条也需要校验最后资费失效时间
        if (offerInstList.size() == 1) {
            ruleCommonParam.getParams().put("lastFeeCheckFlag", "lastFeeCheck");
        }
        this.checkOfferInstFeeListSplit(sceneInstId, ruleCommonParam, checkOfferInstList);
        if (offerInstList.size() > 1) {
            int length = offerInstList.size() - 1;
            for (int i = 0; i < length; i++) {
                checkOfferInstList.clear();
                checkOfferInstList.add(offerInstList.get(i));
                checkOfferInstList.add(offerInstList.get(i + 1));
                // 存在最后一个资费
                if (length - i == 1) {
                    ruleCommonParam.getParams().put("lastFeeCheckFlag", "lastFeeCheck");
                }
                this.checkOfferInstFeeListSplit(sceneInstId, ruleCommonParam, checkOfferInstList);
            }
        }
    }

    /**
     * 校验资费生效模式，失效模式
     * @param sceneInstId
     * @param ruleCommonParam
     * @param checkOfferInstFeeList
     */
    public void checkOfferInstFeeEffExpMode(String sceneInstId,RuleCommonParam ruleCommonParam,List<KiteOfferInst> checkOfferInstFeeList){
        Map param = ruleCommonParam.getParams();
        if(KiteMapUtils.isEmpty(param)){
            param = new HashMap<String,Object>();
            ruleCommonParam.setParams(param);
        }
        param.put("feeCheckFlag", "feeEffExpMode");
        //执行规则校验
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.onAddAdditionalOfferInstCheck(sceneInstId, ruleCommonParam,checkOfferInstFeeList);
        this.dealOfferInstFeeEffExpModeResult(ruleResponse,sceneInstId);
    }

    @Override
    public DataRuleResult onAddOfferInstCheck(String sceneInstId, RuleCommonParam ruleCommonParam) {
        KiteRuleResponse kiteRuleResponse = CuccRuleTrigger.onAddOfferInstCheck(sceneInstId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(kiteRuleResponse);
    }

    @Override
    public DataRuleResult SafeProductOnDelProdInstCheck(String sceneInstId, RuleCommonParam ruleCommonParam){
        KiteRuleResponse kiteRuleResponse = CuccRuleTrigger.SafeProductOnDelProdInstCheck(sceneInstId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(kiteRuleResponse);
    }

    @Override
    public DataRuleResult memberDelCheck(String sceneInstId, RuleCommonParam ruleCommonParam){
        KiteRuleResponse kiteRuleResponse = CuccRuleTrigger.memberDelCheck(sceneInstId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(kiteRuleResponse);
    }

    @Override
    public DataRuleResult checkOnOrderPreview(String sceneInstId, String custId, RuleCommonParam ruleCommonParam) {
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        //合同信息
        List contactInfosList = this.getContactInfo(sceneInstId, custId,sceneInst.getServiceOfferId());
        //收货信息
        List deliverryInfoList = this.getDeliveryInfosList(sceneInstId);

        Map<String,Object> param = new HashMap<String,Object>();
        param.put("contracts", contactInfosList);
        param.put("deliveryInfos", deliverryInfoList);
        ruleCommonParam.setParams(param);

        if (GeneralSwitchUtils.isSwitchOpened(SwitchConsts.EXECUTE_RULE_ASYNC)) {
            CompletableFuture<DataRuleResult> future = CompletableFuture.supplyAsync(FunctionWrapper.wrapLoginInfo(
                (Supplier<KiteRuleResponse>) () -> cuccRuleTriggerService
                    .checkOrderPreViewCommon(sceneInstId, custId, ruleCommonParam))).thenCombine(CompletableFuture
                .supplyAsync(FunctionWrapper.wrapLoginInfo((Supplier<KiteRuleResponse>) () -> cuccRuleTriggerService
                    .checkOnOrderPreview(sceneInstId, custId, ruleCommonParam))), (commonResponse, ruleResponse) -> {
                RuleResponseUtils.cheackRuleResp(commonResponse);
                return RuleResponseUtils.cheackRuleResp(ruleResponse);
            });
            return future.join();
        }

        //ET_ORDER_PREVIEW_COMMON
        KiteRuleResponse commonResponse = cuccRuleTriggerService.checkOrderPreViewCommon(sceneInstId, custId, ruleCommonParam);
        RuleResponseUtils.cheackRuleResp(commonResponse);


        KiteRuleResponse ruleResponse = cuccRuleTriggerService.checkOnOrderPreview(sceneInstId, custId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }

    @Override
    public DataRuleResult checkOnOrderPreViewCommon(String sceneInstId,String custId,RuleCommonParam ruleCommonParam){
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        //合同信息
        List contactInfosList = this.getContactInfo(sceneInstId, custId,sceneInst.getServiceOfferId());
        //收货信息
        List deliverryInfoList = this.getDeliveryInfosList(sceneInstId);
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("contracts", contactInfosList);
        param.put("deliveryInfos", deliverryInfoList);
        ruleCommonParam.setParams(param);

        //ET_ORDER_PREVIEW_COMMON
        KiteRuleResponse commonResponse = cuccRuleTriggerService.checkOrderPreViewCommon(sceneInstId,custId,ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(commonResponse);
    }

    @Override
    public DataRuleResult cuccCheckOnOrderPreview(String sceneInstId, String custId, RuleCommonParam ruleCommonParam) {
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);

        //合同信息
        List contactInfosList = this.getContactInfo(sceneInstId, custId,sceneInst.getServiceOfferId());
        //收货信息
        List deliverryInfoList = this.getDeliveryInfosList(sceneInstId);

        Map<String,Object> param = Optional.ofNullable(ruleCommonParam.getParams()).orElse(new HashMap<>());
        param.put("contracts", contactInfosList);
        param.put("deliveryInfos", deliverryInfoList);
        ruleCommonParam.setParams(param);

        if (GeneralSwitchUtils.isSwitchOpened(SwitchConsts.EXECUTE_RULE_ASYNC)) {
            CompletableFuture<DataRuleResult> future = CompletableFuture.supplyAsync(FunctionWrapper.wrapLoginInfo(
                (Supplier<KiteRuleResponse>) () -> cuccRuleTriggerService
                    .cuccCheckOrderPreViewCommon(sceneInstId, custId, ruleCommonParam))).thenCombine(CompletableFuture
                .supplyAsync(FunctionWrapper.wrapLoginInfo((Supplier<KiteRuleResponse>) () -> cuccRuleTriggerService
                    .cuccCheckOnOrderPreview(sceneInstId, custId, ruleCommonParam))), (commonResponse, ruleResponse) -> {
                RuleResponseUtils.cheackRuleResp(commonResponse);
                return RuleResponseUtils.cheackRuleResp(ruleResponse);
            });
            return future.join();
        }

        // 趸交资费校验（趸交终止-资费失效时间校验），获取趸交资费实例id，与对应新增资费订单id
        this.getSinglePaymentFeeAddOrderId(sceneInstId, ruleCommonParam);

        //ET_ORDER_PREVIEW_COMMON
        KiteRuleResponse commonResponse = cuccRuleTriggerService.cuccCheckOrderPreViewCommon(sceneInstId, custId, ruleCommonParam);
        RuleResponseUtils.cheackRuleResp(commonResponse);


        KiteRuleResponse ruleResponse = cuccRuleTriggerService.cuccCheckOnOrderPreview(sceneInstId, custId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }

    /**
     * 获取趸交资费实例id，与对应新增资费订单id
     * @author zhang.song
     * @date 2022-03-28 19:47
     * @param sceneInstId
     * @param ruleCommonParam
     * @return void
     */
    public void getSinglePaymentFeeAddOrderId(String sceneInstId, RuleCommonParam ruleCommonParam) {
        String serviceOfferId = getServiceOfferId(sceneInstId);
        if (KiteStringUtils.isEqual(serviceOfferId, "2826")) {
            List<Map> offerInstFeeList = CuccRuleTrigger.getOfferInstFee(sceneInstId);

            // 是否有修改的趸交资费
            boolean isModifySinglePaymentFee = offerInstFeeList.stream().anyMatch(offerInstfee ->
                KiteStringUtils.isEqual(KiteMapUtils.getString(offerInstfee, "payType"), LocalKeyConsts.FEE_PAY_TYPE_ONE_OFF)
                    && KiteStringUtils.isEqual(KiteMapUtils.getString(offerInstfee, "actionType"), ActionType.M.name()));
            if(!isModifySinglePaymentFee) {
                return;
            }

            String serialNumber = RuleUtil.getQuerySceneInstService().listCommonAttrs(sceneInstId).stream().filter(kiteAttr ->
                KiteStringUtils.isEqual(kiteAttr.getFieldName(), LocalKeyConsts.BUSINESS_NUMBER)).findAny().map(KiteAttr::getValue).orElse(null);
            List<String> feeInstanceIds = new ArrayList<>();
            offerInstFeeList.forEach(offerInstfee -> {
                String payType = KiteMapUtils.getString(offerInstfee, "payType");
                // 趸交资费
                if(KiteStringUtils.isEqual(payType, "one-off")) {
                    Map<String, Object> attrMap = KiteMapUtils.getMap(offerInstfee, "attrMap");
                    // 资费实例id
                    String instId = AttrUtil.getValue(attrMap.get("210004688"));
                    Optional.ofNullable(instId).ifPresent(feeInstanceIds::add);
                }
            });
            List<Map<String, String>>  feeInstIdAndOrderIdList = paymentService.getFeeAddOrderId(serialNumber, feeInstanceIds);
            ruleCommonParam.getParams().put("feeInstIdAndOrderIdList", feeInstIdAndOrderIdList);
        }
    }

    @Override
    public DataRuleResult cuccCheckOnOrderPreViewCommon(String sceneInstId,String custId,RuleCommonParam ruleCommonParam){
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        //合同信息
        List contactInfosList = this.getContactInfo(sceneInstId, custId,sceneInst.getServiceOfferId());
        //收货信息
        List deliverryInfoList = this.getDeliveryInfosList(sceneInstId);
        Map<String,Object> param = new HashMap<String,Object>();
        param.put("contracts", contactInfosList);
        param.put("deliveryInfos", deliverryInfoList);
        ruleCommonParam.setParams(param);

        //ET_ORDER_PREVIEW_COMMON
        KiteRuleResponse commonResponse = cuccRuleTriggerService.cuccCheckOrderPreViewCommon(sceneInstId,custId,ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(commonResponse);
    }


    @Override
    public DataRuleResult singlePaymentFeePayChargeCheck(String amount, String serialNumber, RuleCommonParam ruleCommonParam) {
        // 获取趸交资费信息
        Map payInfo = new HashMap();
        payInfo.put("amount", amount);
        payInfo.put("serialNumber", serialNumber);
        ruleCommonParam.getParams().put("payInfo", payInfo);

        KiteRuleResponse ruleResponse = cuccRuleTriggerService.singlePaymentFeePayChargeCheck(ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }

    @Override
    public DataRuleResult specialLineStartRentCheck(String sceneInstId, RuleCommonParam ruleCommonParam) {
        // 操作类型
        String bizType = querySceneInstService.getExtParameterValue(sceneInstId, "bizType");
        Map<String, Object> ruleParam = new HashMap<>();
        ruleParam.put("bizType", bizType);
        ruleCommonParam.setParams(ruleParam);
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.specialLineStartRentCheck(sceneInstId, ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }

    public static <T> List<T> transArray2List(T[] arrays){
        if(Objects.isNull(arrays) || arrays.length == 0){
            return Collections.EMPTY_LIST;
        }
        List<T> resultList = new ArrayList<T>();
        for(int i = 0; i< arrays.length;i++){
            resultList.add(arrays[i]);
        }
        return resultList;
    }

    public List getContactInfo(String scenInstId,String custId,String ServiceOfferId){
        List contactInfoList = new ArrayList();
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(scenInstId);
        String rootInstId = sceneInst.getRootInstId();
        KiteOfferInst rootofferInst = querySceneInstService.getOfferInst(custId,rootInstId);
        if(Objects.nonNull(rootofferInst)){
            String cateId = Optional.ofNullable(rootofferInst.getAttr("cateId")).map(KiteAttr::getDefaultValue).orElse("");
            if (!isAddRoleProduct(cateId)){
                List<KiteOfferInstContract> kiteOfferInstContractRelList = RuleUtil.getQuerySceneInstService().
                    listOfferInstContracts(custId, rootofferInst.getOfferInstId());
                if (KiteListUtils.isNotEmpty(kiteOfferInstContractRelList)){
                    kiteOfferInstContractRelList.stream().forEach(kiteOfferInstContract ->{
                        if(!ActionType.D.equals(kiteOfferInstContract.getActionType())){
                            Map map = KiteMapUtils.beanToMap(kiteOfferInstContract);
                            String serviceOfferIds = DcPublicCache.getPCode("2021102201","serviceOfferIds");
                            if(KiteStringUtils.isEmpty(kiteOfferInstContract.getContractNo()) && KiteStringUtils.isNotEmpty(serviceOfferIds) && !KiteStringUtils.equalsAny(ServiceOfferId,serviceOfferIds.split(SymbolConsts.COMMA))){
                                map.put("contactflag","1");
                            }
                            contactInfoList.add(map);
                        }
                    });
                }
            }
        }
        return contactInfoList;
    }

    /**
     * 判断附加产品
     * @param cateId
     * @return
     */
    public static boolean isAddRoleProduct(String cateId) {
        DcPublic dcPublic = DcPublicCache.get("20201112001", cateId);
        return Objects.nonNull(dcPublic);
    }


    public List<Map<String, Object>> getDeliveryInfosList(String sceneInstId) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        List<Map<String, Object>> deliveryInfos = RuleUtil.getQuerySceneInstService().getExtParameterValue(sceneInstId, "offerInstDeliveryInfos");
        if(KiteListUtils.isNotEmpty(deliveryInfos)){
            for(Map<String, Object> deliveryInfo : deliveryInfos){
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("instId",KiteMapUtils.getString(deliveryInfo,"instId"));
                List<KiteAttr> kiteAttrs = (List<KiteAttr>) deliveryInfo.get("kiteAttrs");
                StringBuilder builder = new StringBuilder();
                for(KiteAttr attr :kiteAttrs){
                    if(KiteStringUtils.isEmpty(attr.getObjId())){
                        if(KiteStringUtils.equals(attr.getAttrValueTypeId(), KeyValues.DROPDOWN)){
                            resultMap.put(attr.getFieldName(),KiteStringUtils.isEmpty(attr.getValue())? "":attr.getValueDesc());
                        }else{
                            resultMap.put(attr.getFieldName(),KiteStringUtils.isEmpty(attr.getValue())? "":attr.getValue());
                        }
                    }else{
                        builder.append(KiteStringUtils.isEmpty(attr.getValue())? "":attr.getValue());
                    }
                }
                String deliveryAddress = builder.toString();
                resultMap.put("deliveryAddress",deliveryAddress);
                resultList.add(resultMap);
            }
        }
        return resultList;
    }

    /**
     * 获取服务提供Id
     */
    public static String getServiceOfferId(String sceneInstId) {
        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(sceneInstId);
        String serviceOfferId = sceneInst.getServiceOfferId();

        //追加订购
        String addOrder = RuleUtil.getQuerySceneInstService().getExtParameterValue(sceneInstId, LocalKeyConsts.ADD_ORDE);
        if (KiteStringUtils.equals(addOrder, "T")) {
            serviceOfferId = "2019";
        }
        return serviceOfferId;
    }

    public static List<KiteOfferInst> getOfferInstFee(String sceneInstId) {
        List<KiteOfferInst> offerInstList = new ArrayList<>();
        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(sceneInstId);
        offerInstList.addAll(RuleUtil.getQuerySceneInstService().listMainOfferInsts(sceneInstId));
        offerInstList.addAll(RuleUtil.getQuerySceneInstService().listPromotionOfferInsts(sceneInstId));
        List offerInstFeeList = new ArrayList();
        for (KiteOfferInst kiteofferInst : offerInstList) {
            List<KiteOfferInst> offerInstFees = RuleUtil.getQuerySceneInstService().listAdditionalOfferInstsFromMainOfferInst(sceneInst.getCustId(), kiteofferInst.getOfferInstId());
            if (KiteListUtils.isNotEmpty(offerInstFees)) {
                offerInstFees.stream().forEach(offerInstfee -> {
                    Map offerInstFee = KiteMapUtils.beanToMap(offerInstfee);
                    offerInstFeeList.add(offerInstFee);
                });
            }
        }
        return offerInstFeeList;
    }


    /**
     * 【趸交】订单终止校验规则埋点
     */
    public void singlePaymentFeeTerminationCheck(String sceneInstId, RuleCommonParam ruleCommonParam, List<KiteOfferInst> checkOfferInstFeeList) {
        // 服务场景id
        String serviceOfferId = getServiceOfferId(sceneInstId);

        //属性值校验
        Map<String, Object> checkAttrValueMap = new HashMap<>();
        //取公共属性
        List<KiteAttr> checkCommonAttrList = RuleUtil.getQuerySceneInstService().listCommonAttrs(sceneInstId).stream().filter(kiteAttr ->
            KiteStringUtils.equalsAny(kiteAttr.getFieldName(), LocalKeyConsts.BUSINESS_NUMBER)).collect(Collectors.toList());
        checkCommonAttrList.stream().forEach(kiteAttr -> {
            checkAttrValueMap.put(kiteAttr.getFieldName(), kiteAttr);
        });

        KiteAttr kiteAttr = (KiteAttr)checkAttrValueMap.get("business_number");
        String serialNumber = kiteAttr.getValue();
        boolean singlePaymentFeeTerminationCheckFlag = false;
        // 产品变更场景
        if (KiteStringUtils.equals("2826", serviceOfferId)) {
            for (KiteOfferInst offerInstfee : checkOfferInstFeeList) {
                Map<String, KiteAttr> attrMap = offerInstfee.getAttrMap();
                // 对应月租资费编码
                Object singlePaymentRentFeeCodeAttr = attrMap.get("200003243");
                // 不为空表示该资费是趸交资费，对应月租资费编码为趸交资费独有属性
                if (singlePaymentRentFeeCodeAttr != null) {
                    // 资费实例id
                    String instId = AttrUtil.getValue(attrMap.get("210004688"));
                    // 生效时间
                    String singlePaymentEffDate = AttrUtil.getValue(attrMap.get("200000172"));
                    LocalDate effDateLocal = LocalDate.parse(singlePaymentEffDate, DateTimeFormatter.ofPattern(RuleDateUtil.DEFAULTPATTERN));
                    // 失效时间属性
                    Object singlePaymentExpDateObj = attrMap.get("200000173");
                    String singlePaymentExpDate = AttrUtil.getValue(attrMap.get("200000173"));
                    // 失效时间变更属性
                    String singlePaymentExpIsEdit = LocalRuleUtil.getStringValueFromAttr(singlePaymentExpDateObj, "isEdit");
                    LocalDate expDateLocal = LocalDate.parse(singlePaymentExpDate, DateTimeFormatter.ofPattern(RuleDateUtil.DEFAULTPATTERN));

                    // 当前时间
                    LocalDate nowLocal = LocalDate.now();
                    // 比较日期,是否存在生效的趸交资费
                    long daysEffDiff = ChronoUnit.DAYS.between(effDateLocal, nowLocal);
                    long daysExpDiff = ChronoUnit.DAYS.between(nowLocal, expDateLocal);
                    // 生效时间大于等于当前时间，失效时间小于等于当前时间，视为存在生效的趸交资费
                    if (daysEffDiff >= 0 || daysExpDiff <= 0) {
                        // 割接数据不允许趸交终止
                        this.judgeExistInstId(offerInstfee);
                        // 是否打印发票，若已打印发票，则拦截。只有发票为未打印或者返销状态才可以发起中止
                        singlePaymentFeeTerminationCheckFlag = paymentService.isIssueInvoice(serialNumber, instId);
                    }
                }
            }
        }

        Map<String, Object> param = new HashMap<String, Object>();
        param.put("singlePaymentFeeTerminationCheckFlag", singlePaymentFeeTerminationCheckFlag);
        ruleCommonParam.setParams(param);

        //执行规则校验
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.singlePaymentFeeTerminationCheck(sceneInstId, ruleCommonParam);
        RuleResponseUtils.cheackRuleResp(ruleResponse);
    }

    /**
     * 获取趸交资费与月租费对应关系
     * @param offerInstList
     * @return
     */
    private Map<String, List> getOneOffFeeRelation(List<KiteOfferInst> offerInstList) {
        List<DcPublic> dcPublicList = DcPublicCache.getByPkey("20211027", "OfferInstFee");
        Map<String, String> codeMap = new HashMap<>();
        if (KiteListUtils.isNotEmpty(dcPublicList)) {
            for (DcPublic dcPublic:dcPublicList) {
                if (KiteStringUtils.isNotEmpty(dcPublic.getCodeb()) && KiteStringUtils.isNotEmpty(dcPublic.getCodea())) {
                    codeMap.put(dcPublic.getCodeb(),dcPublic.getCodea());
                }
            }
        }
        Map<String, List> offerInstFeeListMap = new HashMap<>();
        for (KiteOfferInst offerInstFee : offerInstList) {
            String specId = offerInstFee.getSpecId();
            if (KiteMapUtils.isNotEmpty(codeMap) && codeMap.keySet().contains(specId)) {
                specId = codeMap.get(specId);
            }
            List<KiteOfferInst> itemList;
            if (offerInstFeeListMap.containsKey(specId)) {
                itemList = offerInstFeeListMap.get(specId);
            } else {
                itemList = new ArrayList<>();
                offerInstFeeListMap.put(specId, itemList);
            }
            itemList.add(offerInstFee);
        }
        return offerInstFeeListMap;
    }

    /**
     * 对销售品实例按照生效时间排序
     * @param kiteOfferInstList
     */
    private static void sortByEffTime(List<KiteOfferInst> kiteOfferInstList) {
        //按照生效时间排序
        kiteOfferInstList.sort(new Comparator<KiteOfferInst>() {
            @Override
            public int compare(KiteOfferInst offerInst1, KiteOfferInst offerInst2) {
                KiteAttr effDateAttr1 = offerInst1.getAttr("200000172");
                KiteAttr effDateAttr2 = offerInst2.getAttr("200000172");
                Date effDate1 = KiteDateUtils.parseStrToDate(effDateAttr1.getValue());
                Date effDate2 = KiteDateUtils.parseStrToDate(effDateAttr2.getValue());
                if(Objects.nonNull(effDate1) && Objects.nonNull(effDate2)){
                    return effDate1.compareTo(effDate2);
                }
                return 0;
            }
        });
    }

    /**
     * 对于割接数据，找不到资费实例ID的，需要校验不让进行趸交终止
     */
    private void judgeExistInstId(KiteOfferInst offerInstFee) {
        Map<String, KiteAttr> attrMap = offerInstFee.getAttrMap();
        // 资费实例id
        String instId = AttrUtil.getValue(attrMap.get("210004688"));
        KiteAttr expTimeAttr = offerInstFee.getAttr("200000173");
        // 对该资费进行终止操作
        if (ActionType.M.equals(offerInstFee.getActionType()) && KiteStringUtils.isEmpty(instId) &&
            Objects.nonNull(expTimeAttr) && !KiteStringUtils.equals(expTimeAttr.getValue(), expTimeAttr.getOriginValue())) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("没有找到此资费新增时的订单，不允许趸交终止");
        }
    }

    /**
     * 设置付费关系校验
     * @param ruleCommonParam
     * @return
     */
    @Override
    public DataRuleResult PIARPayMemberCheck(RuleCommonParam ruleCommonParam) {
        KiteRuleResponse ruleResponse = cuccRuleTriggerService.PIARPayMemberCheck(ruleCommonParam);
        return RuleResponseUtils.cheackRuleResp(ruleResponse);
    }
}
